'''
Author: quweiwei 1377981689@qq.com
Date: 2025-10-23 11:22:32
LastEditors: quweiwei 1377981689@qq.com
LastEditTime: 2025-10-23 14:44:41
FilePath: \生成视频AI\audio.py
Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
'''
import requests
import sys
import os
sys.stdout.reconfigure(encoding='utf-8')

def addAudio(voice_id,text,name):
    url = f"https://api.elevenlabs.io/v1/text-to-speech/{voice_id}?output_format=mp3_44100_128"

    headers = {
        "Content-Type": "application/json",
        "xi-api-key": os.getenv("ELEVENLABS_API_KEY"),  # 🔑 你的API Key
    }

    data = {
        "text": f"{text}",
        "model_id": "eleven_multilingual_v2",
    }

    response = requests.post(url, headers=headers, json=data)

    # 检查返回状态
    if response.status_code == 200:
        # 保存为 mp3 文件
        with open(f"data/audios/{name}.mp3", "wb") as f:
            f.write(response.content)
        print(f"语音已保存为 {name}.mp3")
        return f"data/audios/{name}.mp3"
    else:
        print(f"请求失败: {response.status_code}")
        print(response.text)

import librosa
import numpy as np
import soundfile as sf

def merge_conversation_audio(first_paths, second_paths, output_name):
    """
    使用 librosa 模拟自然对话合并逻辑（交替讲话 + 静音间隔）
    """
    def load_audio(path):
        if os.path.exists(path):
            y, sr = librosa.load(path, sr=None)
            return y, sr
        return None, None

    first_segments, second_segments = [], []
    sr = None

    for path in first_paths:
        y, s = load_audio(path)
        if y is not None:
            first_segments.append(y)
            sr = s

    for path in second_paths:
        y, s = load_audio(path)
        if y is not None:
            second_segments.append(y)
            sr = s

    # 如果采样率未知，默认 44100
    sr = sr or 44100

    def silence(duration_ms):
        return np.zeros(int(sr * duration_ms / 1000))

    # 合并第一个说话者的轨道
    first_output = np.array([], dtype=np.float32)
    for i, seg in enumerate(first_segments):
        if i > 0:
            # 在第二个说话人之前的所有语音时长加静音
            prev_second_len = sum(len(x) for x in second_segments[:i]) if i <= len(second_segments) else sum(len(x) for x in second_segments)
            first_output = np.concatenate([first_output, silence(prev_second_len * 1000 / sr)])
        first_output = np.concatenate([first_output, seg])

    # 补尾静音
    first_total = len(first_output)
    second_total = sum(len(x) for x in second_segments)
    if first_total < second_total:
        first_output = np.concatenate([first_output, silence((second_total - first_total) * 1000 / sr)])

    # 合并第二个说话者的轨道
    second_output = np.array([], dtype=np.float32)
    current_time = 0
    for i, seg in enumerate(second_segments):
        prev_first_len = sum(len(x) for x in first_segments[:i+1]) if i < len(first_segments) else sum(len(x) for x in first_segments)
        silence_len = max(prev_first_len - current_time, 0)
        if silence_len > 0:
            second_output = np.concatenate([second_output, silence(silence_len * 1000 / sr)])
            current_time += silence_len
        second_output = np.concatenate([second_output, seg])
        current_time += len(seg)

    # 补尾静音
    if len(second_output) < len(first_output):
        second_output = np.concatenate([second_output, silence((len(first_output) - len(second_output)) * 1000 / sr)])

    # 输出保存
    os.makedirs("audio", exist_ok=True)
    first_output_path = f"audio/{output_name}_1.mp3"
    second_output_path = f"audio/{output_name}_2.mp3"

    sf.write(first_output_path, first_output, sr)
    sf.write(second_output_path, second_output, sr)

    return first_output_path, second_output_path

voice_ids = {
    "woman_1": "Xb7hH8MSUJpSbSDYk0k2",
    "woman_2": "AZnzlk1XvdvUeBnXmlld",
    "woman_3": "MF3mGyEYCl7XYWbV9V6O",
    "woman_4": "cgSgspJ2msm6clMCkdW9",
    "man_1": "pqHfZKP75CvOlQylNhV4",
    "man_2": "nPczCjzI2devNBz1zQrb",
    "man_3": "N2lVS1w4EtoT3dr4eOWO",
    "man_4": "IKne3meq5aSn9XLyUdCD",
}

if __name__ == "__main__":
    # 街头采访 - 有男女对话，生成两个音频
    # addAudio("Xb7hH8MSUJpSbSDYk0k2", "Os jogos sul-americanos estão pegando fogo ultimamente! Principalmente o confronto entre o Palmeiras e a LDU de Quito, e também o Racing contra o Flamengo. O que você acha dessas duas partidas?", "街头采访_女")
    # addAudio("pqHfZKP75CvOlQylNhV4", "Verdade, vai ser emocionante! O Palmeiras vem numa fase superestável — manda bem em casa e o ataque tá bem afiado. Contra a LDU de Quito, acho que continuam dominando o jogo. Meus palpites de placar são: 3:1 ou 4:1 pro Palmeiras.", "街头采访_男")

    # 街头采访 单男 - 只有一个说话者，生成一个音频
    # addAudio("N2lVS1w4EtoT3dr4eOWO", "Os jogos sul-americanos estão chamando muita atenção ultimamente, e eu acho que todos valem a pena acompanhar de perto. Falando do confronto que vem aí — Palmeiras x LDU de Quito. Pelos números e pelo momento, o Palmeiras tem uma vantagem clara — parece muito mais preparado pra vencer. Já a LDU é um time guerreiro, mas fora de casa costuma jogar de forma mais recuada, mais na defensiva.", "街头采访_单男")

    # 打造人设 男 - 只有一个说话者，生成一个音频
    # addAudio("pqHfZKP75CvOlQylNhV4", "Como um analista de futebol que há muito tempo acompanha o cenário sul-americano, eu sempre sigo um princípio: só entendendo os dados é que dá pra entender o jogo. Na próxima rodada da Copa Libertadores, o Palmeiras vai enfrentar a LDU de Quito. O Palmeiras chega forte jogando em casa, com o elenco completo e um ataque cada vez mais eficiente. Contra a LDU, o objetivo é bem claro: jogar com segurança e garantir os três pontos.", "打造人设_男")

    # 打造人设 女 - 只有一个说话者，生成一个音频
    # addAudio("MF3mGyEYCl7XYWbV9V6O", "Muita gente acha que análise de futebol é só olhar o placar ou contar com a sorte, mas pra mim, o futebol é uma arte de lógica e detalhes. Nos últimos dias tenho acompanhado de perto os dados do grande jogo da Copa Libertadores: Palmeiras x LDU de Quito. O Palmeiras continua mandando bem em casa — o time controla o jogo, troca passes com rapidez e está finalizando cada vez melhor. A LDU tem uma defesa resistente, mas fora de casa o desempenho deles é bem instável. Esse duelo vai ser uma verdadeira batalha de ritmo e paciência, e sinceramente? O Palmeiras leva vantagem.", "打造人设_女")

    # 赛事预测 男 - 只有一个说话者，生成一个音频
    # addAudio("N2lVS1w4EtoT3dr4eOWO", "Muita gente assiste futebol só pela emoção, mas eu presto atenção nos detalhes e nas mudanças de ritmo e desempenho. Nos próximos dias, temos dois grandes jogos sul-americanos: Palmeiras x LDU de Quito. Analisando o contexto geral, vejo o Palmeiras com boas chances de vencer em casa — o time está em ótima fase e deve impor seu ritmo. Palpite de placar: 3x1 / 4x1. Racing x Flamengo. Aqui, minha aposta vai pro Flamengo. Mesmo fora de casa, o time tem mais qualidade e poder ofensivo pra buscar o resultado. Previsão: 1x2 / 0x2", "赛事预测_男")

    # 男女版赛事预测 - 有男女对话，生成多个音频
    # merge_conversation_audio([
        # addAudio("pqHfZKP75CvOlQylNhV4", "Esses dois jogos da Libertadores prometem bastante, o que você acha deles?", "男女版赛事预测_男_1")
        # addAudio("Xb7hH8MSUJpSbSDYk0k2", "Sim, os dois são grandes confrontos, vale a pena ficar de olho.No primeiro — Palmeiras x LDU de Quito — o Palmeiras está em ótima fase jogando em casa.Acho que tem grandes chances de vencer. Palpite de placar: 3x1 ou 4x1.", "男女版赛事预测_女_1")
        # addAudio("pqHfZKP75CvOlQylNhV4", "E o outro jogo, Racing x Flamengo?", "男女版赛事预测_男_2")
        # addAudio("Xb7hH8MSUJpSbSDYk0k2", "Acredito que o Flamengo leva uma vitória apertada. Palpite: 1x2 ou 0x2.", "男女版赛事预测_女_2")
        addAudio("pqHfZKP75CvOlQylNhV4", "Valeu, agora já tenho um rumo certo!", "男女版赛事预测_男_3")
        # "男女版赛事预测"
    # )

    # 平台优惠推广 男 - 只有一个说话者，生成一个音频
    # addAudio("IKne3meq5aSn9XLyUdCD", "Venha fazer parte da AFUN e aprenda com especialistas a entender as tendências e análises do futebol — transforme o seu amor pelo esporte em conhecimento! Cadastre-se e receba benefícios especiais. Ganhe bônus ao participar mais. Acompanhe as análises dos profissionais e aproveite uma experiência mais completa no mundo do futebol", "平台优惠推广_男")

    # 平台优惠推广 女 - 只有一个说话者，生成一个音频
    # addAudio("MF3mGyEYCl7XYWbV9V6O", "Genteee , segue as análises dos especialistas e vem curtir o futebol com muito mais emoção e leveza! Olha só os mimos: Se é nova por aqui, já ganha um presentinho de boas-vindas! Participando mais, você desbloqueia várias vantagens. Acompanhe as previsões e aprenda a entender o jogo como uma verdadeira expert! bora viver essa vibe boa do futebol juntinhas!", "平台优惠推广_女")